﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows.Input;
using Workbench.Models;
using Workbench.Operations;
using Workbench.Shared;

namespace Workbench.Presentation
{
    public class POSTypesTreeViewModel : ViewModelBase
    {
        public POSTypesTreeViewModel()
        {
            addCommand = new _AddCommand(this);
            removeCommand = new _RemoveCommand(this);

            StateContanainer.Current.POSTypes.CollectionChanged -= POSTypes_CollectionChanged;
            StateContanainer.Current.POSTypes.CollectionChanged += POSTypes_CollectionChanged;
        }

        public ObservableCollection<POSTypeViewModel> POSTypes
        {
            get
            {
                return StateContanainer.Current.POSTypes;
            }
        }

        private void POSTypes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (var treeNode in e.NewItems.Cast<POSTypeViewModel>())
                {
                    treeNode.SetPropertyChangedHandlerRecursive(isSelected_PropertyChanged);
                    treeNode.Children.CollectionChanged -= POSTypes_CollectionChanged;
                    treeNode.Children.CollectionChanged += POSTypes_CollectionChanged;
                }
            }
        }
        private void isSelected_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName != "IsSelected")
                return;

            var treeNode = sender as POSTypeViewModel;
            if (treeNode == null)
            {
                return;
            }

            if (treeNode.IsSelected)
            {
                SelectedNode = treeNode;
            }
            else
            { 
                if(SelectedNode == treeNode)
                {
                    SelectedNode = null;
                }
            }
        }

        private POSTypeViewModel selectedNode;
        public POSTypeViewModel SelectedNode
        {
            get { return selectedNode; }
            set { selectedNode = value; RaisePropertyChanged(); }
        }

        #region AddCommand

        readonly _AddCommand addCommand;
        public ICommand AddCommand
        {
            get { return addCommand; }
        }

        private class _AddCommand : ICommand
        {
            readonly POSTypesTreeViewModel viewModel;

            public _AddCommand(POSTypesTreeViewModel viewModel)
            {
                this.viewModel = viewModel;
                viewModel.PropertyChanged += viewModel_PropertyChanged;
            }

            void viewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == "SelectedNode")
                {
                    RaiseCanExecuteChanged();
                }
            }

            public bool CanExecute(object parameter)
            {
                return (viewModel.SelectedNode as POSTypeViewModel) != null;
            }

            public void RaiseCanExecuteChanged()
            {
                if(CanExecuteChanged != null) 
                    CanExecuteChanged(null, EventArgs.Empty);
            }

            public void Execute(object parameter)
            {
                var parentPOSType = viewModel.SelectedNode;
                viewModel.AddPOSType(parameter as string, parentPOSType);
            }

            public event EventHandler CanExecuteChanged;
        }

        #endregion AddCommand

        #region RemoveCommand

        readonly _RemoveCommand removeCommand;
        public ICommand RemoveCommand
        {
            get { return removeCommand; }
        }

        private class _RemoveCommand : ICommand
        {
            readonly POSTypesTreeViewModel viewModel;

            public _RemoveCommand(POSTypesTreeViewModel viewModel)
            {
                this.viewModel = viewModel;
            }

            public bool CanExecute(object parameter)
            {
                return viewModel.SelectedNode != null;
            }

            public void RaiseCanExecuteChanged()
            {
                if(CanExecuteChanged!=null)
                    CanExecuteChanged(null, EventArgs.Empty);
            }

            public void Execute(object parameter)
            {
                var viewModelToDelete = viewModel.SelectedNode;
                viewModel.RemovePOSType(viewModelToDelete);
            }

            public event EventHandler CanExecuteChanged = (sender, args) => { };
        }

        #endregion AddCommand

        #region Actions
          
        public void Unload()
        {
            StateContanainer.Current.POSTypes.Clear();
            this.SelectedNode = null;
        }

        public async void LoadPOSTypes(IEnumerable<ProjectFileModel> contextFiles)
        {
            var posTypes = await ProjectOperations.GetPOSTypesWithStatisticsAsync(contextFiles);
            StateContanainer.Current.POSTypes.Clear();
            StateContanainer.Current.POSTypes.AddRange(posTypes.Select(x => new POSTypeViewModel(x)));
        }

        public void AddPOSType(string name, POSTypeViewModel parentPOSType)
        {
            var dataModel = ProjectOperations.AddPOSType(name, parentPOSType != null ? parentPOSType.DataModel : null);
            if (dataModel.ParentPOSTypeId == 0)
            {
                StateContanainer.Current.POSTypes.Add(new POSTypeViewModel(dataModel));
            }
        }

        public void RemovePOSType(POSTypeViewModel posTypeViewModelToRemove)
        {
            ProjectOperations.RemovePOSType(posTypeViewModelToRemove.DataModel);
            StateContanainer.Current.POSTypes.Remove(posTypeViewModelToRemove);
        }
        
        #endregion 
    
    }
}
